package org.example.sunrise.core;

import javafx.scene.image.Image;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.example.sunrise.domains.Coordinate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.function.Consumer;

@Getter
@Setter
public class Sprite {
    private Coordinate position;
    private Coordinate velocity;
    private Coordinate scale;
    private Coordinate bound;
    private Image image;
    private boolean needDestroy;
    private List<Image> images;
    private ScheduledFuture<?> future;
    @Setter(AccessLevel.NONE)
    private int imageIndex = 0;
    private final List<Consumer<Sprite>> onMouseClickedListeners = new ArrayList<>();
    private final List<Consumer<Sprite>> onUpdateListeners = new ArrayList<>();
    private final List<Consumer<Sprite>> onReadyListeners = new ArrayList<>();

    public Sprite() {
        onUpdateListeners.add(Sprite::move);
    }

    public void setOnMouseClicked(Consumer<Sprite> listener) {
        onMouseClickedListeners.add(listener);
    }

    public void setOnUpdate(Consumer<Sprite> listener) {
        onUpdateListeners.add(listener);
    }

    public void setOnReady(Consumer<Sprite> listener) {
        onReadyListeners.add(listener);
    }

    public void onMouseClicked() {
        onMouseClickedListeners.forEach(listener -> listener.accept(this));
    }

    public void onUpdate() {
        onUpdateListeners.forEach(listener -> listener.accept(this));
    }

    public void onReady() {
        onReadyListeners.forEach(listener -> listener.accept(this));
    }

    public void move() {
        if (position.x() < bound.x() && position.y() < bound.y()) {
            setPosition(new Coordinate(position.x() + velocity.x(), position.y() + velocity.y()));
        }
    }

    public void changeAppearance() {
        setImage(images.get(imageIndex));
        imageIndex = (imageIndex + 1) % images.size();
    }

    public boolean isChosen(double x, double y) {
        return x >= position.x() && x <= position.x() + scale.x() && y >= position.y() && y <= position.y() + scale.y();
    }
}
